#include <iostream>
#include <typeinfo>

using namespace std;

void test_basicType()
{
	char c = 'a';
	unsigned char uc = 'a';
	short s = 2;
	unsigned short us = 3;
	int i = 4;
	unsigned int ui = 5;
	long l = 6;
	unsigned long ul = 7;
	float f = 1.0f;
	double d = 2;

	cout<<"--- "<<__func__<<" ---"<<endl;
	cout<<"c  : "<<typeid(c).name()<<endl;
	cout<<"uc : "<<typeid(uc).name()<<endl;
	cout<<"s  : "<<typeid(s).name()<<endl;
	cout<<"us : "<<typeid(us).name()<<endl;
	cout<<"i  : "<<typeid(i).name()<<endl;
	cout<<"ui : "<<typeid(ui).name()<<endl;
	cout<<"l  : "<<typeid(l).name()<<endl;
	cout<<"ul : "<<typeid(ul).name()<<endl;
	cout<<"f  : "<<typeid(f).name()<<endl;
	cout<<"d  : "<<typeid(d).name()<<endl;
}

struct C {
	void print(){cout<<"struct C"<<endl;}
};

void test_struct()
{
	cout<<"--- "<<__func__<<" ---"<<endl;
	C c;
	cout<<"C c  : "<<typeid(c).name()<<endl;
}

class A {
	public:
		void print() {cout<<"A"<<endl;}
};

class B: public A {
	public:
		void print() {cout<<"B"<<endl;}
};

void test_class()
{
	cout<<"--- "<<__func__<<" ---"<<endl;

	A *a1 = new A();
	A a2;
	cout<<"A *a1 (a)   : "<<typeid(a1).name()<<endl;
	cout<<"A *a1 (*a1) : "<<typeid(*a1).name()<<endl;
	cout<<"A a2  (a2)  : "<<typeid(a2).name()<<endl;
	cout<<"(A)         : "<<typeid(A).name()<<endl;
}

class D {
	public:
		virtual void print() {cout<<"C"<<endl;}
};
class E: public D {
	public:
		void print() {cout<<"D"<<endl;}
};
class F: public D {
	public:
		void print() {cout<<"F"<<endl;}
};

void test_inherit()
{
	cout<<"--- "<<__func__<<" ---"<<endl;
	A *a = new B();
	D *d = new E();
	cout<<"A *a = new B() (a)  : "<<typeid(a).name()<<endl;
	cout<<"A *a = new B() (*a) : "<<typeid(*a).name()<<endl;
	cout<<"D *d = new E() (d)  : "<<typeid(d).name()<<endl;
	cout<<"D *d = new E() (*d) : "<<typeid(*d).name()<<endl;
}

void handle1(D *d)
{
	if (typeid(*d) == typeid(D)) {
		cout<<"D truly"<<endl;
	} else if (typeid(*d) == typeid(E)) {
		cout<<"E truly"<<endl;
	} else if (typeid(*d) == typeid(F)) {
		cout<<"F truly"<<endl;
	}
}

void handle2(D *d)
{
	if (dynamic_cast<E*>(d)) {
		cout<<"E truly"<<endl;
	} else if (dynamic_cast<F*>(d)) {
		cout<<"F truly"<<endl;
	} else {
		cout<<"D truly"<<endl;
	}
}

void test_handle()
{
	cout<<"--- "<<__func__<<" ---"<<endl;
	D *d = new D();
	D *d1 = new E();
	D *d2 = new F();
	handle2(d);
	handle1(d1);
	handle2(d2);
}


int main(int argc, char const* argv[])
{
	test_basicType();
	test_struct();
	test_class();
	test_inherit();
	test_handle();
	return 0;
}
